﻿#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<windows.h>
#include<fstream>
#ifndef HXLBMPFILEH 
#define HXLBMPFILEH

class HXLBMPFILE  
{  BYTE *Imagedata; 
public:  int imagew,imageh;  
		 int iYRGBnum;//1：灰度，3：彩色  
		 RGBQUAD palette[256]; 
		 BYTE *pDataAt(int h,int Y0R0G1B2 = 0); 
		 BOOL AllocateMem(); 
		 BOOL LoadBMPFILE(char *fname); 
		 BOOL SaveBMPFILE(char *fname);
		 HXLBMPFILE(); 
		 ~HXLBMPFILE(); 
};
#endif
   HXLBMPFILE::HXLBMPFILE()  
{  
	Imagedata=NULL; 
   for (int i = 0; i< 256;i++)  
   {  
	   palette [i].rgbBlue = 
       palette [i].rgbGreen =  palette [i].rgbRed = i;
       palette [i].rgbReserved = 0;  
   } 
   iYRGBnum = 0;
   imagew = imageh = 0;
} 
   HXLBMPFILE::~HXLBMPFILE() 
{ 
	if (Imagedata) delete[] Imagedata;  
}
   BYTE *HXLBMPFILE::pDataAt(int h, int Y0R0G1B2)
   {
   if(iYRGBnum<=Y0R0G1B2)
   return NULL;
   int w=imagew*h+Y0R0G1B2*imagew*imageh;
   return Imagedata+w;
   }
   
   BOOL HXLBMPFILE::AllocateMem(){
   int w=imagew*imageh*iYRGBnum;
   if(Imagedata){
   delete[]Imagedata;
   Imagedata=NULL;
   }
   Imagedata=new BYTE[w];
   if(Imagedata)
	   memset(Imagedata,0,w);
   return (Imagedata!=NULL);
   }
  
   BOOL HXLBMPFILE::LoadBMPFILE (char *cFilename)
   {
   FILE *f;
   if(strlen(cFilename)<1)
	   return false;
   f=fopen(cFilename,"r+b");
   if(f==NULL){
   return FALSE;
   }
   BITMAPFILEHEADER fh; 
   BITMAPINFOHEADER ih;
   fread(&fh,sizeof(BITMAPFILEHEADER),1,f);
   if (fh.bfType!=0x4d42) 
   {
	   fclose(f);
	   return FALSE;
   }//"BM" 
   fread (&ih,sizeof(BITMAPINFOHEADER),1,f);
   if ( (ih.biBitCount!= 8)&&(ih.biBitCount!= 24) )
   {
   fclose(f);
   return FALSE;
   }
   iYRGBnum = ih.biBitCount/8;
   imagew = ih.biWidth;
   imageh = ih.biHeight;
   if(!AllocateMem()) {fclose (f);return FALSE;}
   if ( iYRGBnum==1) fread (palette,sizeof(RGBQUAD),256,f);
   fseek(f,fh.bfOffBits,SEEK_SET);
   int w4b = (imagew * iYRGBnum + 3 )/4 *4, i, j;
   BYTE *ptr;
   ptr = new BYTE [ w4b];
   if (ptr==NULL) {fclose(f);return FALSE;}
   if (iYRGBnum == 1)
   {
	   for (i=imageh -1; i>=0; i--){
	   fread(ptr,w4b,1,f); 
	   memmove(pDataAt (i),ptr, imagew);
	   }
   }
   if ( iYRGBnum == 3)
   {
	   for ( i = imageh - 1; i >= 0; i--){
	   fread(ptr,w4b,1,f);
	   for ( j = 0; j < imagew; j++){
	    *(pDataAt (i,0)+j) = *(ptr+j*3 + 2);
		*(pDataAt (i,1)+j) = *(ptr+j*3 + 1);  
		*(pDataAt (i,2)+j) = *(ptr+j*3 + 0);
	   }
	   }
   }
   delete[] ptr;
   fclose(f);
   return TRUE;
}
   BOOL HXLBMPFILE::SaveBMPFILE (char *cFilename){
   if (!Imagedata) return FALSE;
   FILE *f; if (strlen(cFilename)<1) return FALSE;
   f=fopen(cFilename,"w+b");
   if (f==NULL) return FALSE;
   BITMAPFILEHEADER fh; 
   BITMAPINFOHEADER ih;
   memset(&ih,0,sizeof(BITMAPINFOHEADER)); 
   fh.bfType = 0x4d42;
   fh.bfReserved1 = fh.bfReserved2 = 0;
   fh.bfOffBits = sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER) + ( (iYRGBnum == 1)?256*sizeof(RGBQUAD):0); ih.biSize = 40; ih.biPlanes = 1;
   ih.biWidth = imagew;
   ih.biHeight = imageh; 
   ih.biBitCount = 8 * iYRGBnum; 
   int w4b = (imagew*iYRGBnum +3)/4*4; 
   ih.biSizeImage = ih.biHeight *w4b;
   fh.bfSize = fh.bfOffBits + ih.biSizeImage; 
   fwrite(&fh,sizeof(BITMAPFILEHEADER),1,f); 
   fwrite(&ih,sizeof(BITMAPINFOHEADER),1,f); 
   if ( iYRGBnum == 1) 
	   fwrite(palette,sizeof(RGBQUAD),256,f);
   BYTE* ptr; int i,j; ptr = new BYTE [w4b]; 
   if (ptr==NULL)
   {
	   fclose(f); 
	   return FALSE;
   } 
   memset(ptr,0,w4b);
   if (iYRGBnum == 1) 
   { 
	   for ( i=ih.biHeight -1;i>=0;i--) 
        { 
			memmove(ptr, pDataAt(i),ih.biWidth);
			fwrite(ptr,w4b,1,f);
	   }
   }
   if (iYRGBnum == 3) 
   { 
	   for ( i=ih.biHeight -1;i>=0;i--)
   {
	   for ( j = 0; j < ih.biWidth ; j++) 
	   { 
	   *(ptr+j*3 +0) =*(pDataAt(i,2)+j);
	   *(ptr+j*3 +1) = *(pDataAt(i,1)+j); 
	  *(ptr+j*3 +2 )= *(pDataAt(i,0)+j); 
	   }
	   fwrite(ptr,w4b,1,f); 
   }
   }
   delete[] ptr;
   fclose(f); return TRUE;
   }
   bool readBmp(char *bmpName){
   FILE *fp=fopen(bmpName,"rb");
   if(fp==0)
	   return 0;
   fseek(fp,sizeof(BITMAPFILEHEADER),0);//跳过位图文件头结构BITMAPFILEHEADER
    BITMAPINFOHEADER head;
	fread(&head,sizeof( BITMAPINFOHEADER),1,fp);//获取图像宽、搞、每个像素所占位数
	//bmpWidth=head.biWidth;
   }
   bool changePalette(char *filename)//更改调色板的值
   {
   HXLBMPFILE bmpfile; 
	int i,j,v;
	if (!bmpfile.LoadBMPFILE (filename))
		return 1;
	// do other processing with the imagedata//
	HXLBMPFILE bf;
	bf.imagew = bmpfile.imagew;
	bf.imageh = bmpfile.imageh;
	bf.iYRGBnum = bmpfile.iYRGBnum;
	if (!bf.AllocateMem()) return 1;
	//bf.iYRGBnum=bmpfile.iYRGBnum=1;
	for (i=0;i<bmpfile.imageh;i++)
		for (j=0;j<bmpfile.imagew;j++)
		{
		bf.pDataAt(i)[j]=bmpfile.pDataAt (i)[j];
		}
		//bf.iYRGBnum=1;//将彩色图片变成灰度图片
	for (int i = 0; i< 256;i++)  
   {  
	   bf.palette [i].rgbBlue =i;
	   bf.palette [i].rgbGreen = 50+i;
	   bf. palette [i].rgbRed = 150+i;
       bf.palette [i].rgbReserved = 0;  
   } 
		bf.SaveBMPFILE ("1_1.bmp");
   }
   bool fanbaiBmp(char *filename)//将伪彩图片反白
   {
     HXLBMPFILE bmpfile; 
	int i,j,v;
	if (!bmpfile.LoadBMPFILE (filename))
		return 1;
	// do other processing with the imagedata//
	HXLBMPFILE bf;
	bf.imagew = bmpfile.imagew;
	bf.imageh = bmpfile.imageh;
	bf.iYRGBnum = bmpfile.iYRGBnum;
	if (!bf.AllocateMem()) return 1;
	//bf.iYRGBnum=bmpfile.iYRGBnum=1;
	for (i=0;i<bmpfile.imageh;i++)
		for (j=0;j<bmpfile.imagew;j++)
		{
		bf.pDataAt(i)[j]=255-bmpfile.pDataAt (i)[j];
		}
		//bf.iYRGBnum=1;//将彩色图片变成灰度图片
	for (int i = 0; i< 256;i++)  
   {  
	   bf.palette [i].rgbBlue =255- bmpfile.palette[i].rgbBlue;
	   bf.palette [i].rgbGreen = 255- bmpfile.palette[i].rgbGreen;
	   bf. palette [i].rgbRed = 255- bmpfile.palette[i].rgbRed;
       bf.palette [i].rgbReserved = 0;  
   } 
		bf.SaveBMPFILE ("fanbai_1_2.bmp");
   }
   bool saveTxt(char *filename)//将bmp图片数据存为txt
   {
   HXLBMPFILE bmpfile; 
   if(!bmpfile.LoadBMPFILE(filename))
	   return false;
   FILE *file;
   if(!(file=fopen("bmp1.txt","w+")))
   {
   printf("打开文件失败");
   return false;
   }
   for(int i=0;i<bmpfile.imageh;i++)
	{
		for(int j=0;j<bmpfile.imagew;j++)
	   {
		   fprintf(file,"%d ",bmpfile.pDataAt(i)[j]);
	   }
		fprintf(file,"\n");
   }
   fclose(file);
   return true;
   }
   bool changeToGrayscale(char *filename)
   {
    HXLBMPFILE bmpfile; 
	int i,j,v;
	if (!bmpfile.LoadBMPFILE (filename))
		return 1;
	// do other processing with the imagedata//
	HXLBMPFILE bf;
	bf.imagew = bmpfile.imagew;
	bf.imageh = bmpfile.imageh;
	bf.iYRGBnum = bmpfile.iYRGBnum;
	if (!bf.AllocateMem()) return 1;
	//bf.iYRGBnum=bmpfile.iYRGBnum=1;
	for (i=0;i<bmpfile.imageh;i++)
		for (j=0;j<bmpfile.imagew;j++)
		{
		bf.pDataAt(i)[j]=bmpfile.pDataAt (i)[j];
		}
	bf.iYRGBnum=1;//将彩色图片变成灰度图片
	for (int i = 0; i< 256;i++)  
   {  
	   bf.palette [i].rgbBlue =bf.palette [i].rgbGreen = 
	   bf. palette [i].rgbRed = i;
       bf.palette [i].rgbReserved = 0;  
   } 
		bf.SaveBMPFILE ("hometown_1.bmp");
   }
int main()
{
		fanbaiBmp("b.bmp");//将灰度图片反白
		changePalette("1.bmp");//更改灰度图片的调色板
		saveTxt("b.bmp");//保存灰度bmp图片的数据
		changeToGrayscale("hometown.bmp");//将彩色图片变成灰度图片
		printf("program ends!\n");
	    return 0;
}